using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using Icinetic.FeedCategorySample.Entities;

namespace Icinetic.FeedCategorySample.Services.Repositories
{
    public class RssItemRepository : BaseRepository, IRepository<RssItem>
    {
        public RssItemRepository()
            : base()
        {
        }

        public virtual int Add(RssItem _item)
        {
            return ExecuteWithRetry<int>(() =>
            {
                int id = 0;

                using (var db = new SQLite.SQLiteConnection(DbPath))
                {
                    db.RunInTransaction(() =>
                    {
                        if (SearchCount(rssItem => rssItem.Content == _item.Content) == 0)
                            id = db.Insert(_item);
                    });
                }

                return id;
            }, OperationType.Write);
        }

        public virtual void Add(List<RssItem> _items)
        {
            ExecuteWithRetry(() =>
            {
                using (var db = new SQLite.SQLiteConnection(DbPath))
                {
                    db.RunInTransaction(() =>
                    {
                        foreach (RssItem item in _items)
                        {
                            if (SearchCount(rssItem => rssItem.Content == item.Content) == 0)
                                db.Insert(item);
                        }
                    });
                }
            }, OperationType.Write);
        }

        public virtual void Change(RssItem _item)
        {
            ExecuteWithRetry(() =>
            {
                using (var db = new SQLite.SQLiteConnection(DbPath))
                {
                    db.RunInTransaction(() =>
                    {
                        db.Update(_item);
                    });
                }
            }, OperationType.Write);
        }

        public virtual void Remove(RssItem _item)
        {
            ExecuteWithRetry(() =>
            {
                using (var db = new SQLite.SQLiteConnection(DbPath))
                {
                    db.RunInTransaction(() =>
                    {
                        db.Delete(_item);
                    });
                }
            }, OperationType.Write);
        }

        public virtual RssItem Find(int oid)
        {
            return ExecuteWithRetry<RssItem>(() =>
            {
                RssItem item = null;

                using (var db = new SQLite.SQLiteConnection(DbPath))
                {
                    item = db.Table<RssItem>().Where(x => x.OID == oid).SingleOrDefault();
                }

                return item;
            }, OperationType.Read);
        }

        public virtual IList<RssItem> FindAll(int count = 0, int index = 0)
        {
            return ExecuteWithRetry<IList<RssItem>>(() =>
            {
                IList<RssItem> items = null;

                using (var db = new SQLite.SQLiteConnection(DbPath))
                {
                    if (count > 0)
                        items = db.Table<RssItem>().Take(count).Skip(count * index).OrderByDescending(x => x.DateArticle).ToList();
                    else
                        items = db.Table<RssItem>().OrderByDescending(x => x.DateArticle).ToList();
                }

                return items;
            }, OperationType.Read);
        }

        public virtual IList<RssItem> Search(Expression<Func<RssItem, bool>> searchCriteria, Expression<Func<RssItem, object>> orderBy, bool ascending = true, int pageIndex = 0, int pageSize = 10)
        {
            return ExecuteWithRetry<IList<RssItem>>(() =>
            {
                IList<RssItem> all = null;

                using (var db = new SQLite.SQLiteConnection(DbPath))
                {
                    var query = db.Table<RssItem>()
                                .Where(searchCriteria)
                                .Take(pageSize)
                                .Skip(pageIndex * pageSize);

                    if (orderBy != null)
                        query = ascending ? query.OrderBy(orderBy) : query.OrderByDescending(orderBy);

                    all = query.ToList();
                }

                return all;
            }, OperationType.Read);
        }

        public virtual int SearchCount(Expression<Func<RssItem, bool>> searchCriteria)
        {
            return ExecuteWithRetry<int>(() =>
            {
                int count = 0;

                using (var db = new SQLite.SQLiteConnection(DbPath))
                {
                    var query = db.Table<RssItem>()
                                .Where(searchCriteria);

                    count = query.Count();
                }

                return count;
            }, OperationType.Read);
        }
    }
}	


